package com.java.thread.thread_secrity;

/**
 * 多线程安全问题的解决方式一：同步代码块<p>
 *      synchronized ( 同步监视器 ) { 需要被同步的代码 }
 * <p>
 * 优点：同步的方式，解决了线程安全的问题<p>
 * 缺点：操作同步代码时，只能有一个线程参与，其他线程等待。相当于时一个单线程的过程，效率低。
 */
public class SafeTicketsWindow02 {
    public static void main(String[] args) {
        WindowThread02 ticketsThread02 = new WindowThread02();
        Thread t1 = new Thread(ticketsThread02);
        Thread t2 = new Thread(ticketsThread02);
        Thread t3 = new Thread(ticketsThread02);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

class WindowThread02 implements Runnable {
    private int ticketsNum = 100;

    //由于，Runnable实现多线程，所有线程共用一个实现类的对象，所以三个线程都共用实现类中的这个Object类的对象。
    Object obj = new Object();
    //如果时继承Thread类实现多线程，那么需要使用到static Object obj = new Object();

    public void run() {

        //Object obj = new Object();
        //如果Object对象在run()方法中创建，那么每个线程运行都会生成自己的Object类的对象，并不是三个线程的共享对象，所以并没有给加上锁。

        while (true) {
            synchronized (obj) {
                if (ticketsNum > 0) {
                    try {
                        //手动让线程进入阻塞,增大安全性发生的概率
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":\t票号:" + ticketsNum + "\t剩余票数:" + --ticketsNum);
                } else {
                    break;
                }
            }
        }
    }
}
